from django.shortcuts import render

# Create your views here.
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.db.models import Q
from rest_framework import mixins
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
from django.conf import settings
from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler
from rest_framework import permissions
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework import authentication

from users.serializers import SmsSerializer, UserRegisterSerializer, UserDetailSerializer
from utils.yunpian import YunPian
from utils.encrypt import generate_code
from users.models import VerifyCode
# from utils.permissions import IsOwnerOrReadOnly

User = get_user_model()


class CustomBackend(ModelBackend):
    """自定义用户验证"""

    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(username=username) | Q(mobile=username))
            if user.check_password(password):
                return user
        except Exception as e:
            return None


class SmsCodeViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
    """
    发送短信验证码
    """
    serializer_class = SmsSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)  # 在这里如果出错抛异常，drf会捕捉到，抛400的异常
        # 重写下面这一部分
        # self.perform_create(serializer)
        # headers = self.get_success_headers(serializer.data)
        # return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

        mobile = serializer.validated_data['mobile']
        obj_yunpian = YunPian(apikey=settings.YUNPIAN_APIKEY)
        code = generate_code(length=4, schema='number')
        sms_status = obj_yunpian.send_sms(mobile=mobile, code=code)
        # 参考https://www.yunpian.com/doc/zh_CN/domestic/single_send.html文档进行解析
        if sms_status['code'] != 0:
            # 发送失败
            return Response({
                "mobile": sms_status['msg']
            }, status=status.HTTP_400_BAD_REQUEST)
        else:
            obj_verify_code = VerifyCode(code=code, mobile=mobile)
            obj_verify_code.save()
            headers = self.get_success_headers(serializer.data)
            return Response({
                "mobile": mobile
            }, status=status.HTTP_201_CREATED, headers=headers)


class UserViewSet(mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """
    用户
    """
    queryset = User.objects.all()
    authentication_classes = (
        JSONWebTokenAuthentication,
        authentication.SessionAuthentication,
        authentication.BasicAuthentication
    )

    # 注册的时候（post）使用下面的序列化类，但是用户详情怎么办？
    # 因此需要重载get_serializer_class以动态获得不同欧冠的serializer class
    # serializer_class = UserRegisterSerializer
    def get_serializer_class(self):
        if self.action == "retrieve":
            return UserDetailSerializer
        elif self.action == "create":
            return UserRegisterSerializer
        return UserDetailSerializer

    # IsAuthenticated的权限控制不适用于创建用户的时候，所以permission_classes应该是动态的
    # 当注册的时候，允许所有人访问：ALLOWANY
    # 其他情况需要注册
    # permission_classes = (permissions.IsAuthenticated, IsOwnerOrReadOnly, )
    # 通过源码，我们发现可以重写APIView中的get_permissions方法实现
    def get_permissions(self):
        # 只有ViewSet才有这个action属性，APIView什么的都没有的
        if self.action == 'retrieve':
            return [permissions.IsAuthenticated()]
        elif self.action == 'create':
            return []
        return []

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 重载，以向前端传递token,实现注册后自动登陆
        user = self.perform_create(serializer)
        payload = jwt_payload_handler(user)
        res_dict = serializer.data
        res_dict['token'] = jwt_encode_handler(payload)
        res_dict['name'] = user.name if user.name else user.username

        headers = self.get_success_headers(serializer.data)
        return Response(res_dict, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        return serializer.save()

    def get_object(self):
        return self.request.user
